package com.example.meitu.api.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.example.meitu.api.common.Result;
import com.example.meitu.api.common.UserLoginContextHolder;
import com.example.meitu.api.dto.*;
import com.example.meitu.api.service.ArticleStatisticService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/statistic")
@Slf4j
public class StatisticController {

    @Resource
    private ArticleStatisticService articleStatisticService;

//    public static final String MING_XING_MING_REN = "自媒体-明星名人";
    public static final String MING_XING_MING_REN = "自媒体-明星名人大类";

//    public static final String ZHONG_YANG_MEI = "传统媒体-中央媒";

    public static final String ZHONG_YANG_MEI = "传统媒体-中央媒体大类";



    /**
     * 对外提供接口，生成日统计表数据
     * @return
     */
    @PostMapping("/calcBrandMediaStatistic")
    public Result calcBrandMediaStatistic(@RequestBody @Valid CalcBrandMediaStatisticDTO calcBrandMediaStatisticDTO){
        List<Integer> brandIds = new ArrayList<>();
        brandIds.add(calcBrandMediaStatisticDTO.getBrandId());

        List<Integer> mediaIds = new ArrayList<>();
        String medisIds = calcBrandMediaStatisticDTO.getMediaIds();
        if (StringUtils.isNotBlank(medisIds)){
            String[] arr = medisIds.split(",");
            for (String s : arr) {
                mediaIds.add(Integer.parseInt(s));
            }
        }

        articleStatisticService.calcBrandMediaStatistic(brandIds, mediaIds,
                calcBrandMediaStatisticDTO.getStartTimm(), calcBrandMediaStatisticDTO.getEndTimm());
        return Result.success();
    }

    /**
     * 概览页统计
     * @param brandId
     * @param startTime
     * @param endTime
     * @return
     */
    @GetMapping("/overview")
    public Result overview(@RequestParam(value = "brandId", required = true) Integer brandId,
                           @RequestParam(value = "startTime", required = true) Integer startTime,
                           @RequestParam(value = "endTime", required = true) Integer endTime,
                           @RequestParam(value = "compareBrandId", required = false) String compareBrandId,
                           @RequestParam(value = "compareStartTime", required = false) Integer compareStartTime,
                           @RequestParam(value = "compareEndTime", required = false) Integer compareEndTime
                           ){
        Integer userId = UserLoginContextHolder.get().getUserId();
        Map map = new HashMap();
        if (StringUtils.isBlank(compareBrandId)) {
            // 查询当前品牌
            OverviewDTO overviewDTO = articleStatisticService.overview(userId,brandId, startTime, endTime);
            return Result.success(overviewDTO);
//            map.put("gailan", overviewDTO);
        } else if (StringUtils.isNotBlank(compareBrandId)){
            // 品牌对比
            List<Integer> compareBrandIds = new ArrayList<>();
            if (StringUtils.isNotBlank(compareBrandId)) {
                compareBrandIds = Arrays.stream(compareBrandId.split(","))
                        .filter(v -> StringUtils.isNotBlank(v))
                        .map(Integer::parseInt).collect(Collectors.toList());
            }
            OverviewParam overviewParam = new OverviewParam(userId,brandId,startTime,endTime,compareBrandIds,null,null);
            DuibiDTO duibiDTO = articleStatisticService.duibi(overviewParam);
            return Result.success(duibiDTO);
//            map.put("duibi", duibiDTO);
        }
        return Result.success(map);
    }

//    private DuibiDTO buildDuibi(List<OverviewDTO> source) {
//        DuibiDTO duibiDTO = new DuibiDTO();
//        for (OverviewDTO overviewDTO : source) {
//            List<List<Integer>> num = duibiDTO.getNum() == null ? new ArrayList<>() : duibiDTO.getNum();
//            num.add(overviewDTO.getNum() == null ? new ArrayList<>() : overviewDTO.getNum());
//            duibiDTO.setOrder(num);
//
//            List<List<BigDecimal>> percent = duibiDTO.getPercent() == null ? new ArrayList<>() : duibiDTO.getPercent();
//            percent.add(overviewDTO.getPercent() == null ? new ArrayList<>() : overviewDTO.getPercent());
//            duibiDTO.setPercent(percent);
//
//            List<List<Integer>> order = duibiDTO.getOrder() == null ? new ArrayList<>() : duibiDTO.getOrder();
//            order.add(overviewDTO.getOrder() == null ? new ArrayList<>() : overviewDTO.getOrder());
//            duibiDTO.setOrder(order);
//
//            List<List<List<String>>> orderList = duibiDTO.getOrderList() == null ? new ArrayList<>() : duibiDTO.getOrderList();
//            orderList.add(overviewDTO.getOrderList() == null ? new ArrayList<>() : overviewDTO.getOrderList());
//            duibiDTO.setOrderList(orderList);
//        }
//        return duibiDTO;
//    }

    /**
     * 覆盖图
     * @param brandId
     * @param startTime
     * @param startTime
     * @param startTime
     * @param startTime
     * @param startTime
     * @param startTime
     * @param endTime
     * @return
     */
    @GetMapping("/fugaitu")
    public Result fugaitu(@RequestParam(value = "brandId", required = true) Integer brandId,
                          @RequestParam(value = "startTime", required = true) Integer startTime,
                          @RequestParam(value = "endTime", required = true) Integer endTime,
                          @RequestParam(value = "type", required = true) String type,
                          @RequestParam(value = "compareBrandId", required = false) String compareBrandId,
                          @RequestParam(value = "compareStartTime", required = false) Integer compareStartTime,
                          @RequestParam(value = "compareEndTime", required = false) Integer compareEndTime){
        Integer userId = UserLoginContextHolder.get().getUserId();
        FugaituParam fugaituParam = new FugaituParam(brandId, startTime, endTime, type, compareBrandId, compareStartTime, compareEndTime, userId);

        //查询出所有的分类卡片
        List<FugaituCardDTO> list = articleStatisticService.fugaitu(fugaituParam);
        //根据scope分组
        Map<String,List<FugaituCardDTO>> scopeMap = list.stream().collect(Collectors.groupingBy(FugaituCardDTO::getScope));
        LinkedHashMap<String,List<FugaituCardDTO>> top = new LinkedHashMap<>();
        top.put("chuantong", scopeMap.get("1"));
        top.put("zixun", scopeMap.get("2"));
        top.put("zimeiti", scopeMap.get("3"));

        LinkedHashMap<String,List<FugaituCardDTO>> subdivide = new LinkedHashMap<>();
        subdivide.put("chuantong", scopeMap.get("4"));
        subdivide.put("zixun", scopeMap.get("5"));
        subdivide.put("zimeiti", scopeMap.get("6"));

        List<Map<String,Object>> topList = new ArrayList<>();
        Map<String,Object> topMap = new HashMap<>();
        topMap.put("type","chuantong");
        topMap.put("list",scopeMap.get("1")==null?new ArrayList<>():scopeMap.get("1"));
        topList.add(topMap);
        Map<String,Object> zixunMap = new HashMap<>();
        zixunMap.put("type","zixun");
        zixunMap.put("list",scopeMap.get("2")==null?new ArrayList<>():scopeMap.get("2"));
        topList.add(zixunMap);
        Map<String,Object> zimeitiMap = new HashMap<>();
        zimeitiMap.put("type","zimeiti");
//        zimeitiMap.put("list",scopeMap.get("3")==null?new ArrayList<>():scopeMap.get("3"));
        // 判断下是否有中央级，会影响到名人明星的位置
        List zimeitiList = sortByChuantong(scopeMap.get("1"),scopeMap.get("3"));
        zimeitiMap.put("list",zimeitiList);
        topList.add(zimeitiMap);

        // 细分圈层补位逻辑，scope 4 5 6 取最大的范围，给小范围的进行补位
        scopeMap = buwei(scopeMap);

        List<Map<String,Object>> subdivideList = new ArrayList<>();
        Map<String,Object> topMap2 = new HashMap<>();
        topMap2.put("type","chuantong");
        topMap2.put("list",scopeMap.get("4")==null?new ArrayList<>():scopeMap.get("4"));
        subdivideList.add(topMap2);
        Map<String,Object> zixunMap2 = new HashMap<>();
        zixunMap2.put("type","zixun");
        zixunMap2.put("list",scopeMap.get("5")==null?new ArrayList<>():scopeMap.get("5"));
        subdivideList.add(zixunMap2);
        Map<String,Object> zimeitiMap3 = new HashMap<>();
        zimeitiMap3.put("type","zimeiti");
        zimeitiMap3.put("list",scopeMap.get("6")==null?new ArrayList<>():scopeMap.get("6"));

        subdivideList.add(zimeitiMap3);

        Map<String,List<Map<String,Object>> > map1 = new HashMap();
        map1.put("top", topList);

        Map<String,List<Map<String,Object>> > map2 = new HashMap();
        map2.put("subdivide", subdivideList);

        List result = new ArrayList();
        result.add(map1);
        result.add(map2);
        return Result.success(result);
    }

    private Map<String, List<FugaituCardDTO>> buwei(Map<String, List<FugaituCardDTO>> scopeMap) {
        List<FugaituCardDTO> chuantongList = scopeMap.get("4") == null ? new ArrayList<>() : scopeMap.get("4");
        List<FugaituCardDTO> zixunList = scopeMap.get("5") == null ? new ArrayList<>() : scopeMap.get("5");
        List<FugaituCardDTO> zimeitiList = scopeMap.get("6") == null ? new ArrayList<>() : scopeMap.get("6");

        //计算最大范围
        List<FugaituCardDTO> maxiList = new ArrayList<>();
        if (chuantongList.size() >= zixunList.size() && chuantongList.size() >= chuantongList.size()) {
            maxiList = chuantongList;
        } else if (zixunList.size() >= chuantongList.size() && zixunList.size() >= zimeitiList.size()) {
            maxiList = zixunList;
        } else {
            maxiList = zimeitiList;
        }


        // 按照maximaList的顺序，把zimeitiList中缺少的元素补充到跟maximaList同样顺序的位置上
        FugaituCardDTO buwei = new FugaituCardDTO();
        buwei.setList(new ArrayList<>());

        for (int i = 0; i < maxiList.size(); i++) {
            FugaituCardDTO max = maxiList.get(i);
            String maxName = max.getName().split("-")[1];
            String maxPName = max.getPName().split("-")[1];

            boolean chuantonghas = false;
            for (FugaituCardDTO chuantong : chuantongList) {
                if (chuantong.getName() == null) {
                    chuantonghas = true;
                    break;
                }
                String name = chuantong.getName().split("-")[1];
                String pname = chuantong.getPName().split("-")[1];
                if (maxName.equals(name) && maxPName.equals(pname)) {
                    chuantonghas = true;
                    break;
               }
            }
            if (!chuantonghas) {
                chuantongList.add(i,buwei);
            }

            boolean zixunhas = false;
            for (FugaituCardDTO zixun : zixunList) {
                if (zixun.getName() == null) {
                    zixunhas = true;
                    break;
                }
                String name = zixun.getName().split("-")[1];
                String pname = zixun.getPName().split("-")[1];
                if (maxName.equals(name) && maxPName.equals(pname)) {
                    zixunhas = true;
                    break;
                }
            }
            if (!zixunhas) {
                zixunList.add(i,buwei);
            }

            boolean zimeitihas = false;
            for (FugaituCardDTO zimeiti : zimeitiList) {
                if (zimeiti.getName() == null) {
                    zimeitihas = true;
                    break;
                }
                String name = zimeiti.getName().split("-")[1];
                String pname = zimeiti.getPName().split("-")[1];
                if (maxName.equals(name) && maxPName.equals(pname)) {
                    zimeitihas = true;
                    break;
                }
            }
            if (!zimeitihas) {
                zimeitiList.add(i,buwei);
            }
        }

        return scopeMap;
    }

    /**
     *
     * @param chuantongList  传统媒体集合
     * @param zimeitiList 自媒体集合
     * @return
     */
    private List sortByChuantong(List<FugaituCardDTO> chuantongList, List<FugaituCardDTO> zimeitiList) {
        if (CollectionUtil.isEmpty(chuantongList)) {
            return new ArrayList();
        }
        if (CollectionUtil.isEmpty(zimeitiList)) {
            return zimeitiList;
        }
        boolean hasZhongyang = false;
        for (FugaituCardDTO fugaituCardDTO : chuantongList) {
            String name = fugaituCardDTO.getName();
            if (name.equals(ZHONG_YANG_MEI)){
                hasZhongyang = true;
                break;
            }
        }
        boolean hasMingren = false;
        for (FugaituCardDTO fugaituCardDTO : zimeitiList) {
            String name = fugaituCardDTO.getName();
            if (name.equals(MING_XING_MING_REN)){
                hasMingren = true;
                break;
            }
        }
        // 选了中央，也选明星名人，明星名人放第一
        if (hasZhongyang && hasMingren) {
            ArrayList<FugaituCardDTO> result = new ArrayList<>();
            Iterator<FugaituCardDTO> iterator = zimeitiList.iterator();
            while(iterator.hasNext()){
                //不能在一个迭代器种多次调用next()。
                FugaituCardDTO fugaituCardDTO = iterator.next();
                if(MING_XING_MING_REN.equals(fugaituCardDTO.getName())){
                    result.add(fugaituCardDTO);
                    iterator.remove();
                }
            }
            result.addAll(zimeitiList);
            return result;
        }

        // 选了中央，没有选明星名人，补位
        if (hasZhongyang && !hasMingren) {
            ArrayList result = new ArrayList();
            FugaituCardDTO buwei = new FugaituCardDTO();
//            buwei.setName(MING_XING_MING_REN);  不显示名称
            buwei.setList(new ArrayList<>());
            result.add(buwei);
            result.addAll(zimeitiList);
            return result;
        }
        //没选中央，选明星名人,明星名人放最后
        if (!hasZhongyang && hasMingren) {
            Iterator<FugaituCardDTO> iterator = zimeitiList.iterator();
            FugaituCardDTO mingren = null;
            while(iterator.hasNext()){
                //不能在一个迭代器种多次调用next()。
                FugaituCardDTO fugaituCardDTO = iterator.next();
                if(MING_XING_MING_REN.equals(fugaituCardDTO.getName())){
                    mingren = fugaituCardDTO;
                    iterator.remove();
                }
            }
            zimeitiList.add(mingren);
            return zimeitiList;
        }
        return zimeitiList;
    }


}

